#第十四章 可迭代的对象、迭代器和生成器

import re

words_re = re.compile(r"\w+")

#实现一个迭代器

class Sentence():

    def __init__(self,text):
        self.text = text
        self.words = words_re.findall(self.text)
    def __getitem__(self,index):
        return self.words[index]
    def __repr__(self):
        return "Sentence(%s)"%self.text

#实现一个标准迭代器的方法
class SentenceIntrator():
    def __init__(self,words):
        self.words = words
        self.index = 0

    def __next__(self): #必须实现
        try:
            word = self.words[self.index]
        except IndexError:
            raise StopIteration()
        self.index += 1
        return word
    def __iter__(self): #必须实现 固定写法
        return self


s = Sentence("wellcome to china")
print(s,s.words,iter(s))

#生成器 理解生成器

def gen_123():
    yield 1
    yield 2
    yield 3

g = gen_123() #生成器函数 返回一个生成器对象
print(g)
for i in g: #生成器是一个迭代器 可以通过for循环
    print(i)

#实现一个等差数列的生成器

class ArithmeticProgresssion():
    def __init__(self,begin,step,end=None):
        self.begin = begin
        self.step = step
        self.end = end
    def __iter__(self):
        index = 0
        forever = self.end is None #无穷的数列
        result = self.begin
        while forever or result+self.step < self.end:
            result = self.begin + self.step * index
            yield result
            index += 1 

ap = ArithmeticProgresssion(1,2,10)
print('ap=',ap,list(ap))

#使用itertools生成生成器

import itertools

def ap_gen(begin,step,end=None): #不是生成器函数 但是返回的还是一个生成器,所以该函数还是生成器工厂函数
    ap_g = itertools.count(begin,step) #构建生成器
    if end is not None:
        ap_g = itertools.takewhile(lambda n : n+step<end,ap_g)
    return ap_g

#标准库中的生成器函数

it = [10,20,30,40,50,60,70,80]
selector_it = [True,0,True,0,1]
cprIt = itertools.compress(it,selector_it) #对比两个迭代对象 如果selector_it上的值是真 则返回it对应位置上的值
print(cprIt,list(cprIt))

print(list(itertools.chain(it,selector_it))) #无缝连接两个可迭代对象

#并行迭代两个迭代对象 以最短的结束

for v1,v2 in zip(it,selector_it): #以最短的结束
    print(v1,v2)

#并行迭代两个迭代对象 以最长的结束

for v1,v2 in itertools.zip_longest(it,selector_it,fillvalue="null"): #以最长的结束 短的对应元素以指定的fillvalue填充
    print(v1,v2)
        

ary = [1,2]
tpl = (1,2)
st = {1,2}
print(type(ary),type(tpl),type(st))

print( all(it) ) #it中全部为真才返回真
print( any(selector_it),iter(it) ) #迭代对象中只要有真则返回真

#iter函数的另一个用法

import random

def d6():
    return random.randint(1,6)

it_d6 = iter(d6,1) # 直到d6函数返回1才会停止,返回一个迭代对象 该对象不包含1元素
print(list(it_d6),list(range(1,6)))

gen = (x for x in range(1,6)) #生成器表达式

